package com.downbox.service.impl;

import com.downbox.config.GlobalExceptionHandler.BusinessException;
import com.downbox.domain.Contribution;
import com.downbox.dto.SubmitReq;
import com.downbox.dto.SubmitResp;
import com.downbox.repository.ContributionRepository;
import com.downbox.service.ContributionService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.regex.Pattern;

/**
 * 投稿服务实现类
 */
@Service
public class ContributionServiceImpl implements ContributionService {

    private static final Logger logger = LoggerFactory.getLogger(ContributionServiceImpl.class);

    @Autowired
    private ContributionRepository contributionRepository;

    @Autowired
    private ObjectMapper objectMapper;

    private static final Pattern SAFE_CONTENT_PATTERN = Pattern.compile("^[^<>]*$");

    @Override
    @Transactional
    public SubmitResp submitContribution(Long userId, SubmitReq req) {
        logger.info("用户[{}]开始提交投稿，类型：{}", userId, req.getType());
        
        // 验证内容安全性（简单过滤）
        validateContent(req);

        try {
            Contribution contribution = new Contribution();
            contribution.setUid(userId);
            contribution.setType(req.getType());
            contribution.setPayload(objectMapper.writeValueAsString(req.getPayload()));
            contribution.setMoodsJson(objectMapper.writeValueAsString(req.getMoods()));
            contribution.setStatus(Contribution.ContributionStatus.PENDING);

            // 保存到数据库
            logger.info("准备保存投稿数据到数据库");
            contribution = contributionRepository.save(contribution);
            logger.info("投稿成功保存到数据库，ID：{}", contribution.getId());

            // 验证是否真的保存成功
            Contribution savedContribution = contributionRepository.findById(contribution.getId())
                .orElseThrow(() -> new BusinessException(500, "保存失败，请重试"));
            logger.info("验证保存成功，数据库中存在投稿记录ID：{}", savedContribution.getId());

            SubmitResp resp = new SubmitResp();
            resp.setId(contribution.getId());
            resp.setStatus(contribution.getStatus().name());
            
            logger.info("投稿处理完成，返回响应：ID={}, 状态={}", resp.getId(), resp.getStatus());
            return resp;
        } catch (JsonProcessingException e) {
            logger.error("JSON序列化失败", e);
            throw new BusinessException(500, "提交失败，请重试");
        } catch (Exception e) {
            logger.error("投稿处理过程中发生异常", e);
            throw e;
        }
    }

    /**
     * 验证投稿内容的安全性和有效性
     */
    private void validateContent(SubmitReq req) {
        // 验证类型
        if (!"text".equals(req.getType()) && !"image".equals(req.getType()) && !"audio".equals(req.getType())) {
            throw new BusinessException(400, "无效的内容类型");
        }

        // 验证payload格式
        if (req.getPayload() == null) {
            throw new BusinessException(400, "内容不能为空");
        }

        // 简单的内容安全检查
        String payloadStr;
        try {
            payloadStr = objectMapper.writeValueAsString(req.getPayload());
            if (!SAFE_CONTENT_PATTERN.matcher(payloadStr).matches()) {
                throw new BusinessException(400, "内容包含不安全字符");
            }
        } catch (JsonProcessingException e) {
            throw new BusinessException(400, "内容格式错误");
        }

        // 验证情绪标签数量
        if (req.getMoods() == null || req.getMoods().size() < 1 || req.getMoods().size() > 3) {
            throw new BusinessException(400, "情绪标签数量必须为1-3个");
        }
    }
}